home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 July: Mac OS SDK / Dev.CD Jul 96 SDK / Dev.CD Jul 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc Development Framework / ODFDev / ODF / Framewrk / FWPart / Sources / FWClpCmd.cpp < prev    next >
Encoding:
Text File  |  1996-04-25  |  12.4 KB  |  492 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWClpCmd.cpp
  4. //    Release Version:    $ ODF 1 $
  5. //
  6. //    Copyright:            (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWFrameW.hpp"
  11.  
  12. #ifndef FWCLPCMD_H
  13. #include "FWClpCmd.h"
  14. #endif
  15.  
  16. #ifndef FWPART_H
  17. #include "FWPart.h"
  18. #endif
  19.  
  20. #ifndef FWINTER_H
  21. #include "FWInter.h"
  22. #endif
  23.  
  24. #ifndef FWFRAME_H
  25. #include "FWFrame.h"
  26. #endif
  27.  
  28. #ifndef FWPRESEN_H
  29. #include "FWPresen.h"
  30. #endif
  31.  
  32. #ifndef FWSELECT_H
  33. #include "FWSelect.h"
  34. #endif
  35.  
  36. #ifndef FWLINK_H
  37. #include "FWLink.h"
  38. #endif
  39.  
  40. #ifndef FWLNKMGR_H
  41. #include "FWLnkMgr.h"
  42. #endif
  43.  
  44. // ----- OS Layer -----
  45.  
  46. #ifndef FWBARRAY_H
  47. #include "FWBArray.h"
  48. #endif
  49.  
  50. #ifndef SLODFSTR_K
  51. #include "SLODFStr.k"
  52. #endif
  53.  
  54. #ifndef SLODFSTR_H
  55. #include "SLODFStr.h"
  56. #endif
  57.  
  58. // ----- OpenDoc Includes -----
  59.  
  60. #ifndef SOM_Module_OpenDoc_Commands_defined
  61. #include <CmdDefs.xh>
  62. #endif
  63.  
  64. #ifndef SOM_ODSession_xh
  65. #include <ODSessn.xh>
  66. #endif
  67.  
  68. #ifndef SOM_ODClipboard_xh
  69. #include <Clipbd.xh>
  70. #endif
  71.  
  72. #ifndef SOM_Module_OpenDoc_StdProps_defined
  73. #include <StdProps.xh>
  74. #endif
  75.  
  76. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  77. #include <StdTypes.xh>
  78. #endif
  79.  
  80. #ifndef SOM_ODStorageUnit_xh
  81. #include <StorageU.xh>
  82. #endif
  83.  
  84. #ifndef SOM_ODLinkSpec_xh
  85. #include <LinkSpec.xh>
  86. #endif
  87.  
  88. //========================================================================================
  89. //    Runtime Info
  90. //========================================================================================
  91.  
  92. #ifdef FW_BUILD_MAC
  93. #pragma segment odfcommands
  94. #endif
  95.  
  96. FW_DEFINE_AUTO(FW_CClipboardCommand)
  97.  
  98. //====================================================================
  99. // FW_CClipboardCommand class
  100. //====================================================================
  101.  
  102. //--------------------------------------------------------------------
  103. // FW_CClipboardCommand constructor
  104. //--------------------------------------------------------------------
  105.  
  106. FW_CClipboardCommand::FW_CClipboardCommand(Environment* ev,
  107.                                 ODCommandID id,
  108.                                 FW_CFrame* frame, 
  109.                                 FW_Boolean canUndo) 
  110. :    FW_CCommand(ev, id, frame, id == kODCommandCopy ? FALSE :canUndo),
  111.     fUpdateID(kODUnknownUpdate),
  112.     fCloneKind(kODCloneCopy),
  113.     fPasteAsHandler(NULL),
  114.     fClipboard(frame->GetPart(ev)->GetSession(ev)->GetClipboard(ev)),
  115.     fSelection(NULL)
  116. {
  117.     short undoMsgID;
  118.     
  119.     switch (id)
  120.     {
  121.         case kODCommandCopy:
  122.             SetCausesChange(ev, FALSE);        // Copy doesn't change the data
  123.             break;
  124.             
  125.         case kODCommandCut:
  126.             fCloneKind = kODCloneCut;
  127.             undoMsgID = FW_kUndoCutMsg;
  128.             break;
  129.             
  130.         case kODCommandPaste:
  131.             fCloneKind = kODClonePaste;
  132.             undoMsgID = FW_kUndoPasteMsg;
  133.             break;
  134.             
  135.         case kODCommandPasteAs:
  136.             fCloneKind = kODClonePaste;
  137.             undoMsgID = FW_kUndoPasteAsMsg;
  138.             break;
  139.             
  140.         case kODCommandClear:
  141.             undoMsgID = FW_kUndoClearMsg;
  142.             break;
  143.         
  144.         default:
  145.             undoMsgID = FW_kDefaultUndoMsg;
  146.             break;
  147.     }
  148.  
  149.     fSelection = frame->GetPresentation(ev)->GetSelection(ev);
  150.     
  151.     if (GetCanUndo(ev))
  152.     {
  153.         FW_CString undoString;
  154.         FW_CString redoString;
  155.         
  156.         ::FW_PrivLoadUndoStrings(ev, undoMsgID, undoString, redoString);
  157.         SetMenuStrings(ev, undoString, redoString);
  158.     }
  159.     FW_END_CONSTRUCTOR
  160. }
  161.  
  162. //--------------------------------------------------------------------
  163. // FW_CClipboardCommand destructor
  164. //--------------------------------------------------------------------
  165.  
  166. FW_CClipboardCommand::~FW_CClipboardCommand()
  167. {
  168.     FW_START_DESTRUCTOR
  169.     delete fPasteAsHandler;
  170. }
  171.  
  172. //--------------------------------------------------------------------
  173. // FW_CClipboardCommand::DoIt
  174. //--------------------------------------------------------------------
  175.  
  176. void FW_CClipboardCommand::DoIt(Environment* ev)    // Override
  177. {
  178.     FW_Boolean result = FALSE;
  179.  
  180.     if (GetCanUndo(ev))
  181.         this->SaveUndoState(ev);    // save current state, for later Undo
  182.  
  183.     switch (GetCommandID(ev))
  184.     {
  185.         case kODCommandCopy:
  186.             this->Copy(ev);
  187.             break;
  188.  
  189.         case kODCommandClear:
  190.             if (this->IsOKtoEdit(ev))
  191.             {
  192.                 this->Clear(ev);
  193.                 result = TRUE;
  194.                 GetPresentation(ev)->ContentUpdated(ev);
  195.             }
  196.             break;
  197.  
  198.         case kODCommandCut:
  199.             if (this->IsOKtoEdit(ev))
  200.             {
  201.                 this->Cut(ev);
  202.                 result = TRUE;
  203.                 GetPresentation(ev)->ContentUpdated(ev);
  204.             }
  205.             break;
  206.  
  207.         case kODCommandPaste:
  208.             if (this->IsOKtoEdit(ev) && this->Paste(ev))
  209.             {
  210.                 result = TRUE;
  211.                 GetPresentation(ev)->ContentUpdated(ev);
  212.             }
  213.             break;
  214.  
  215.         case kODCommandPasteAs:
  216.             if (this->IsOKtoEdit(ev) && this->PasteAs(ev))
  217.             {
  218.                 result = TRUE;
  219.                 GetPresentation(ev)->ContentUpdated(ev);
  220.             }
  221.             break;
  222.     }
  223.  
  224.     if (result == FALSE)
  225.         SetCanUndo(ev, FALSE);
  226.     else if (GetCanUndo(ev))
  227.     {
  228.         this->SaveRedoState(ev);        // save new state, for later Redo
  229.     }
  230. }
  231.  
  232.  
  233. //----------------------------------------------------------------------------------------
  234. //    FW_CClipboardCommand::Cut
  235. //----------------------------------------------------------------------------------------
  236.  
  237. void FW_CClipboardCommand::Cut(Environment* ev)
  238. {
  239.     PreCommand(ev);
  240.     
  241.     this->PrivCopy(ev, false);    // don't write a link spec for a cut
  242.     fSelection->ClearSelection(ev);
  243.     
  244.     // Give the command subclass a chance to do something
  245.     this->CommandDone(ev);
  246. }
  247.  
  248. //----------------------------------------------------------------------------------------
  249. //    FW_CClipboardCommand::Copy
  250. //----------------------------------------------------------------------------------------
  251.  
  252. void FW_CClipboardCommand::Copy(Environment* ev)
  253. {
  254.     PreCommand(ev);
  255.     
  256.     FW_Boolean allowLinking = (fSelection && fSelection->IsSelectionLinkable(ev));
  257.     this->PrivCopy(ev, allowLinking);
  258.     
  259.     CommandDone(ev);
  260. }
  261.  
  262. //----------------------------------------------------------------------------------------
  263. //    FW_CClipboardCommand::Clear
  264. //----------------------------------------------------------------------------------------
  265.  
  266. void FW_CClipboardCommand::Clear(Environment* ev)
  267. {
  268.     PreCommand(ev);
  269.     fSelection->ClearSelection(ev);
  270.     CommandDone(ev);    // Give the command subclass a chance to do something
  271. }
  272.  
  273. //----------------------------------------------------------------------------------------
  274. //    FW_CClipboardCommand::Paste
  275. //----------------------------------------------------------------------------------------
  276.  
  277. FW_Boolean FW_CClipboardCommand::Paste(Environment* ev)
  278. {
  279.     PreCommand(ev);
  280.     return PrivPaste(ev);    // will call CommandDone
  281. }
  282.  
  283. //----------------------------------------------------------------------------------------
  284. //    FW_CClipboardCommand::PrivPaste
  285. //----------------------------------------------------------------------------------------
  286.  
  287. FW_Boolean FW_CClipboardCommand::PrivPaste(Environment* ev)
  288. {
  289.     FW_Boolean result = FALSE;
  290.     
  291.     ODStorageUnit* clipBSU = fClipboard->GetContentStorageUnit(ev);
  292.  
  293.     result = GetPart(ev)->GetDataInterchange(ev)->InternalizeData(ev, fSelection->GetSelectedContent(ev), GetFrame(ev), clipBSU, FW_kClipboardStorage, fCloneKind, NULL) != FW_kInternalizeFailed;
  294.  
  295.     if (result)    
  296.     {
  297.         // notify OpenDoc clipboard
  298.         fUpdateID = fClipboard->ActionDone(ev, fCloneKind);
  299.  
  300.         // Give the command subclass a chance to do something
  301.         CommandDone(ev);
  302.     }
  303.  
  304.     return result;
  305. }
  306.  
  307. //----------------------------------------------------------------------------------------
  308. //    FW_CClipboardCommand::PasteAs
  309. //----------------------------------------------------------------------------------------
  310.  
  311. FW_Boolean FW_CClipboardCommand::PasteAs(Environment* ev)
  312. {
  313.     FW_Boolean result = false;
  314.     FW_VOLATILE(result);
  315.     FW_Boolean handledIt = false;
  316.  
  317.     PreCommand(ev);
  318.  
  319.     FW_TRY
  320.     {
  321.         // Create a PasteAs handler object to do some of the work
  322.         fPasteAsHandler = new FW_MPasteAsHandler(ev, GetFrame(ev));
  323.         result = fPasteAsHandler->HandlePasteAsDialog(ev, fCloneKind, handledIt);
  324.         if (!handledIt)
  325.         {
  326.             SetCommandID(ev, kODCommandPaste);
  327.             result = this->PrivPaste(ev);        // just an ordinary paste
  328.         }
  329.         else if (result)
  330.         {
  331.             // notify OpenDoc clipboard
  332.             fUpdateID = fClipboard->ActionDone(ev, fCloneKind);
  333.     
  334.             // if a link was created, need to post an End transaction
  335.             if (this->GetNewLink(ev) != NULL)
  336.             {
  337.                 SetActionType(ev, kODEndAction);
  338.             }
  339.  
  340.             // Give the command subclass a chance to do something
  341.             this->CommandDone(ev);
  342.         }
  343.     }
  344.     FW_CATCH_BEGIN
  345.     FW_CATCH_EVERYTHING()
  346.     {
  347.         result = false;    // don't re-throw, just return false
  348.     }
  349.     FW_CATCH_END
  350.  
  351.     if (result == false || GetCommandID(ev) == kODCommandPaste)
  352.     {
  353.         // PasteAs handler either not used or not needed
  354.         delete fPasteAsHandler;
  355.         fPasteAsHandler = NULL;
  356.     }
  357.     
  358.     return result;
  359. }
  360.  
  361. //----------------------------------------------------------------------------------------
  362. //    FW_CClipboardCommand::PrivCopy
  363. //----------------------------------------------------------------------------------------
  364.  
  365. void FW_CClipboardCommand::PrivCopy(Environment* ev, FW_Boolean allowLinking)
  366. {
  367.     //---- We have to invalidate any currently pending link ----
  368.     FW_CLinkManager* linkMgr = GetPart(ev)->GetLinkManager(ev);
  369.     if (linkMgr)
  370.         linkMgr->DeletePendingClipboardLink(ev);
  371.  
  372.     //---- Clear any leftover promises on the clipboard ----
  373.     fClipboard->GetContentStorageUnit(ev)->ClearAllPromises(ev);
  374.     GetPart(ev)->GetDataInterchange(ev)->PrivDeletePromises(ev, FW_kClipboardStorage);
  375.  
  376.     //---- Clear all properties and values from the clipboard ----
  377.     fClipboard->Clear(ev);
  378.     
  379.     // [HLX] Getting the clipboardSU before calling fClipboard->Clear(ev) result in 
  380.     // a crash in ExternalizeData when I try to get the draft?????
  381.     ODStorageUnit* clipboardSU = fClipboard->GetContentStorageUnit(ev);
  382.     
  383.     //---- Write new data to the clipboard ----
  384.     GetPart(ev)->GetDataInterchange(ev)->ExternalizeData(ev, 
  385.                                                     fSelection->GetSelectedContent(ev), 
  386.                                                     GetFrame(ev), 
  387.                                                     clipboardSU, 
  388.                                                     FW_kClipboardStorage, 
  389.                                                     fCloneKind);
  390.  
  391.     //---- notify OpenDoc clipboard ----
  392.     fUpdateID = fClipboard->ActionDone(ev, fCloneKind);
  393.             
  394.     // ----- Write out Link Spec if possible -----
  395.     if (allowLinking)
  396.     {
  397.         ODLinkSpec* linkSpec = NULL;
  398.         FW_VOLATILE(linkSpec);
  399.         ODUpdateID updateID = fClipboard->GetUpdateID(ev);
  400.         FW_CByteArray data(&updateID, sizeof(updateID));
  401.  
  402.         FW_TRY
  403.         {
  404.             linkSpec = GetPart(ev)->GetDraft(ev)->CreateLinkSpec(ev, GetPart(ev)->GetODPart(ev), data);
  405.  
  406.             clipboardSU->AddProperty(ev, kODPropLinkSpec);
  407.             linkSpec->WriteLinkSpec(ev, clipboardSU);
  408.         }
  409.         FW_CATCH_BEGIN
  410.         FW_CATCH_EVERYTHING()
  411.         {
  412.             if (linkSpec)
  413.                 delete linkSpec;
  414.             FW_THROW_SAME();
  415.         }
  416.         FW_CATCH_END
  417.  
  418.         delete linkSpec;
  419.  
  420.         // If current selection is already published, just re-use its link
  421.         FW_CLinkSource* linkSource = fSelection->DoFindLinkSource(ev);
  422.         if (linkSource)
  423.             linkSource->SetPendingID(ev, updateID);
  424.         else
  425.             linkSource = linkMgr->NewLinkSource(ev, updateID, GetPresentation(ev));
  426.         linkMgr->SetPendingClipboardLink(ev, linkSource);
  427.     }
  428. }
  429.  
  430. //----------------------------------------------------------------------------------------
  431. //    FW_CClipboardCommand::UndoIt
  432. //----------------------------------------------------------------------------------------
  433.  
  434. void FW_CClipboardCommand::UndoIt(Environment* ev)    // Override
  435. {
  436.     switch (GetCommandID(ev))
  437.     {
  438.         case kODCommandCut:
  439.         case kODCommandPaste:
  440.         case kODCommandPasteAs:
  441.         {
  442.             fClipboard->ActionUndone(ev, fUpdateID, fCloneKind);
  443.         }
  444.     }
  445. }
  446.  
  447. //----------------------------------------------------------------------------------------
  448. //    FW_CClipboardCommand::RedoIt
  449. //----------------------------------------------------------------------------------------
  450.  
  451. void FW_CClipboardCommand::RedoIt(Environment* ev)    // Override
  452. {
  453.     switch (GetCommandID(ev))
  454.     {
  455.         case kODCommandCut:
  456.         case kODCommandPaste:
  457.         case kODCommandPasteAs:
  458.         {
  459.             fClipboard->ActionRedone(ev, fUpdateID, fCloneKind);
  460.         }
  461.     }
  462. }
  463.  
  464. //----------------------------------------------------------------------------------------
  465. //    FW_CClipboardCommand::PreCommand
  466. //----------------------------------------------------------------------------------------
  467.  
  468. void FW_CClipboardCommand::PreCommand(Environment* ev)
  469. {
  470. FW_UNUSED(ev);
  471.     // User may override; 
  472. }
  473.  
  474. //----------------------------------------------------------------------------------------
  475. //    FW_CClipboardCommand::CommandDone
  476. //----------------------------------------------------------------------------------------
  477.  
  478. void FW_CClipboardCommand::CommandDone(Environment* ev)
  479. {
  480. FW_UNUSED(ev);
  481.     // User may override; only gets called if the Command was successful
  482. }
  483.  
  484. //----------------------------------------------------------------------------------------
  485. //    FW_CClipboardCommand::GetNewLink
  486. //----------------------------------------------------------------------------------------
  487.  
  488. FW_CLinkDestination* FW_CClipboardCommand::GetNewLink(Environment* ev) const
  489. {
  490.     return fPasteAsHandler ? fPasteAsHandler->GetNewLink(ev) : NULL;
  491. }
  492.